<?php

class TrimmingService extends AbstractService
{
    /**
     * @var TrimmingService
     */
    private static $instance;

    /**
     * Get instance of TrimmingService.
     *
     * @return TrimmingService
     */
    public static function get()
    {
        if (!self::$instance) {
            self::$instance = new TrimmingService();
        }
        return self::$instance;
    }


    /**
     * Construction.
     */
    protected function __construct()
    {
        parent::__construct();
    }

    /**
     * 处理创建时的逻辑
     *
     * @param int $userId
     * @return void
     */
    public function handleCreate($userId)
    {
    }

    /**
     * 处理登录时的逻辑
     * 1. 更新货架出售信息
     *
     * @param int $userId
     * @return void
     */
    public function handleLogin($userId)
    {

    }

    /**
     * 提供当前 service 数据
     *
     * @param int $userId
     * @param boolean $visitMode default false
     * @return array()
     */
    public function info($userId, $visitMode = false)
    {
        return [];
    }

    /**
     * 购买装饰物
     * @param int $userId
     * @param int $indexId 装饰物ID，配置表`ft_trimming_buy`中的indexId
     * @param bool $throwError 已经拥有了是否抛出异常
     * @param array $trimming default null
     * @return bool
     * @throws SzException
     */
    public function buy($userId, $indexId, $throwError = true, $trimming = null)
    {
        $profileInfoList = SzPersister::get()->getVoList($userId, ModuleProfileConst::ORM_NAME_PROFILE_INFO);
        $trimmingInfo = UserService::get()->getInfo($userId, GameConst::USER_INFO_TYPE_TRIMMING_INFO, $profileInfoList);

        if (is_null($trimmingInfo)) {
            $trimmingInfo = [];
        } else if (in_array($indexId, $trimmingInfo)) {//已经购买过了
            if ($throwError) {
                throw new SzException(28022, $indexId);
            } else {
                return true;
            }
        }

        if (is_null($trimming)) {
            $trimming = SzConfig::get()->loadAppConfig(GameConst::CONFIG_TRIMMING_BUY, $indexId, true);
        }

        if ($trimming['default']) {//不需要购买
            throw new SzException(28021, $indexId);
        }

        $userLevel = UserService::get()->getUserLevel($userId);
        if ($trimming['limitLv'] > $userLevel) {
            throw new SzException(28025, [$indexId, $userLevel]);
        }

        if ($trimming['limitFlower'] > 1) {
            $flowerTotalLevel = SeedService::get()->getSeedTotalLevel($userId);
            if ($trimming['limitFlower'] > $flowerTotalLevel) {
                throw new SzException(28026, [$trimming['limitFlower'], $flowerTotalLevel]);
            }
        }

        $trimmingInfo[] = $indexId;
        UserService::get()->updateProfileInfo($userId, GameConst::USER_INFO_TYPE_TRIMMING_INFO, $trimmingInfo, $profileInfoList);

        $tid = '';
        $goldCount = 0;
        foreach ($trimming['needItem'] as $entityId => $count) {
            GameService::get()->handleEntity($userId, $entityId, $count, true);
            $tid .= $entityId . ':' . $count . '|';
            if ($entityId == GameConst::ENTITY_ACTION_CONSUME_MONEY) {
                $goldCount = $count;
            }
        }
        CommonFunctionService::get()->reportResourceUseDetails(GameConst::FUNC_TRIMMING,$userId,0,$tid,'buy');//消耗资源上报

        // 数据采集:购买装饰物
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USER_ORBIT, array(
            'clientData' => array(
                'tid' => 'Module:ornament|action:buy|',
                'item' => $indexId,
                'value' => 1
            )
        ));

        // 数据采集:购买装饰物消耗
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_RESOURCE_INPUT, array(
            'clientData' => array(
                'tid' => $tid,
                'item' => 'ornament_buy&' . $indexId
            )
        ));

        if ($goldCount) {
            // 数据采集:购买装饰物消耗钻石数量
            StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_USE_GOLD, array(
                'clientData' => array(
                    'tid' => $tid,
                    'item' => 'ornament_buy&' . $indexId
                )
            ));
        }

        // 数据采集:购买解锁装饰物
        StatisticsService::get()->saveLog($userId, GameConst::LOG_TYPE_UPGRADE, array(
            'clientData' => array(
                'tid' => 'objective:ornament|item:' . $indexId . '|',
                'item' => 'fromlevel:|changelev:unlock|targetlev:|'
            )
        ));
        return true;
    }

    /**
     * 更换装饰物, 如果没有则会先购买
     * @param int $userId
     * @param int $indexId
     * @param string $gridId
     * @return bool
     * @throws SzException
     */
    public function replace($userId, $indexId, $gridId)
    {
        $trimmingSettings = SzConfig::get()->loadAppConfig(GameConst::CONFIG_TRIMMING_BUY, null, true);
        if (!isset($trimmingSettings[$indexId])) {
            throw new SzException(10100, array($indexId, GameConst::CONFIG_TRIMMING_BUY));
        }
        $trimming = $trimmingSettings[$indexId];
        if (!$trimming['default']) {//需要购买
            $this->buy($userId, $indexId, false);
        }

        if ($trimming['replace'] == GameConst::TRIMMING_REPLACE_SINGLE) {//单个替换
            if (empty($gridId)) {
                throw new SzException(28025, [$indexId, $gridId]);
            }
            $replaceDefId = array_shift($trimming['itemId']);
            if (!$replaceDefId) {
                throw new SzException(28024, [$indexId, json_encode($trimming['itemId'])]);
            }
            $buildingSetting = SzConfig::get()->loadAppConfig(GameConst::CONFIG_BUILDING, $replaceDefId, true);//判断建筑id是否正确
            /**
             * @var BuildingVo $building
             * @var BuildingVoList $buildingList
             */
            list($decorId, $building, $buildingList) = BuildingService::get()->getGroundAndDecorRecord($userId, $gridId, $buildingSetting['layer']);
            $buildingDefId = $building->getBuildingDefId();

            $theSameGroup = false;
            foreach ($trimmingSettings as $_index => $_setting) {
                if ($_setting['groupId'] == $trimming['groupId'] && in_array($buildingDefId, $_setting['itemId'])) {
                    $theSameGroup = true;
                    break;
                }
            }
            if (!$theSameGroup) {
                throw new SzException(28023, [$indexId, $buildingDefId]);
            }
            $building->setBuildingDefId($replaceDefId);
            $buildingList->updateElement($decorId, $building);
            SzPersister::get()->setVoList($buildingList);
        } else if ($trimming['replace'] == GameConst::TRIMMING_REPLACE_ALL) {// 全体替换
            $replaceInfo = [];
            foreach ($trimmingSettings as $_index => $_setting) {
                if ($_index == $indexId || $_setting['groupId'] != $trimming['groupId'] || $_setting['replace'] != $trimming['replace']) {
                    continue;
                }
                foreach ($_setting['itemId'] as $key => $itemDefId) {
                    if (!isset($trimming['itemId'][$key]) || $itemDefId == $trimming['itemId'][$key]) {
                        continue;
                    }
                    $replaceInfo[$itemDefId] = $trimming['itemId'][$key];
                }
            }
            /**
             * @var BuildingVo $building
             * @var BuildingVoList $buildingList
             */
            $buildingList = SzPersister::get()->getVoList($userId, GameConst::ORM_NAME_BUILDING);
            foreach ($buildingList->getList() as $decorId => $building) {
                $itemDefId = $building->getBuildingDefId();
                if (isset($replaceInfo[$itemDefId])) {
                    $building->setBuildingDefId($replaceInfo[$itemDefId]);
                    $buildingList->updateElement($decorId, $building);
                }
            }
            SzPersister::get()->setVoList($buildingList);
        }
        return true;
    }
}
